package com.resource.service.impl;

import java.net.URI;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import com.resource.dto.ProjectTaskDetailDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.resource.constant.OfficeApiConstants;
import com.resource.dto.ProjectTaskParamDto;
import com.resource.dto.TicketDto;
import com.resource.entity.TicketAgent;
import com.resource.entity.TicketInfo;
import com.resource.entity.TicketReminder;
import com.resource.entity.TicketReply;
import com.resource.enums.TicketChannelEnum;
import com.resource.request.OfficeTaskReplyRequest;
import com.resource.request.OfficeTicketTaskRquest;
import com.resource.request.TicketBaseRequest;
import com.resource.request.TicketReplyRequest;
import com.resource.response.OfficeResultBody;
import com.resource.response.TicketBaseResponse;
import com.resource.service.*;
import com.resource.spring.ApiAssert;
import com.resource.utils.ServiceException;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 工单消息转发业务处理
 * 
 * @Author: xianggaoxiong
 * @Date: 2021-01-07 13:58
 **/
@Slf4j
@Service
public class TicketServiceImpl implements TicketService {
	private final static String EXT_FILE_ID_PROJECT = "d69309173af249c58f1bb26117e10c72";
	private final static String EXT_FILE_ID_PRINCIPAL = "7a09bae4f66c42bfb9d30d90ff0e7870";
	private final static String TICKET_SYS_ACCOUNT_NAME = "service@sijibao.com";
	private final static String TICKET_SYS_ACCOUNT_ID = "953bb20b247b452c87d0be289e2819d9";
	private final static String TICKET_REPLY_URL = "https://www.sobot.com/api/ws/5/ticket/save_user_reply";
	private final static String OFFICE_TAG = "<p>【系统来源】：泛微</p>";
	private final static String TICKET_TAG = "<p>【系统来源】：智齿</p>";
	private final static String CD_AGENT_NAME = "<p>【催单人】：%s</p>";
	private final static String DEAL_AGENT_NAME = "<p>【回复人】：%s</p>";
	@Resource
	private TicketInfoService ticketInfoService;
	@Resource
	private TicketReminderService ticketReminderService;
	@Resource
	private TicketReplyService ticketReplyService;
	@Resource
	private TicketAgentService ticketAgentService;
	@Resource
	private TicketTokenService tokenService;
	@Resource
	private RestTemplate restTemplate;
	@Value("${office.surface.server.url}")
	private String surfaceUrl;

	@Override
	public void syncOffice(TicketBaseRequest request) throws ServiceException {
		log.info("工单消息转发内容:{}", JSONUtil.toJsonStr(request));
		ApiAssert.isNull("工单消息转发内容为空", request.getContent());
		List<Object> contents = request.getContent();
		contents.forEach(content -> {
			JSON parse = JSONUtil.parse(content);
			String isReminder = (String) parse.getByPath("$.is_reminder");
			if (StrUtil.isBlank(isReminder)) {
				return;
			} else if (isReminder.equals("1")) {// 催单
				TicketReminder reminder = new TicketReminder();
				BeanUtil.copyProperties(content, reminder, true);
				// 判断催单信息是否有工单信息
				QueryWrapper<TicketInfo> queryWrapper = new QueryWrapper<>();
				TicketInfo ticketInfo = ticketInfoService
						.getOne(queryWrapper.lambda().eq(TicketInfo::getTicketid, reminder.getTicketid()));
				if (ObjectUtil.isNotNull(ticketInfo)) {
					// 存在工单信息 新增催单信息
					boolean save = ticketReminderService.save(reminder);
					ApiAssert.isFalse("催单信息落库失败", save);
					OfficeTaskReplyRequest build = OfficeTaskReplyRequest.builder()
							.reply_name(reminder.getReminder_agent_name())
							.reply_time(DateUtil.formatDateTime(reminder.getReminder_time()))
							.reply_content(reminder.getReminder_remark()
									+ String.format(CD_AGENT_NAME, reminder.getReminder_agent_name()) + TICKET_TAG)
							.ticket_code(reminder.getTicket_code()).build();
					syncOfficeReply(build);
				}
			} else if (isReminder.equals("0")) {// 新增工单、回复工单、更新工单
				TicketDto ticketDto = new TicketDto();
				BeanUtil.copyProperties(content, ticketDto, true);
				// 如果是泛微直接过去的工单可不用处理
				if (StrUtil.isNotBlank(ticketDto.getReply_content())
						&& StrUtil.endWith(ticketDto.getReply_content(), OFFICE_TAG)) {
					return;
				}
				TicketInfo ticketInfoSave = new TicketInfo();
				BeanUtil.copyProperties(ticketDto, ticketInfoSave, true);
				List<JSONObject> list = Convert.convert(new TypeReference<List<JSONObject>>() {
				}, parse.getByPath("$.extend_fields_list"));
				list.forEach(e -> {
					String fieldid = (String) e.get("fieldid");
					String fieldValue = (String) e.get("field_value");
					if (EXT_FILE_ID_PROJECT.equals(fieldid)) {
						ticketInfoSave.setTicket_project((fieldValue));
					} else if (EXT_FILE_ID_PRINCIPAL.equals(fieldid)) {
						ticketInfoSave.setTicker_principal(fieldValue);
					}
				});
				// 没用项目名称无法在泛微系统项目下创建工单任务
				if (StrUtil.isBlank(ticketInfoSave.getTicket_project())) {
					return;
				}
				// 判断工单是否存在
				QueryWrapper<TicketInfo> queryWrapper = new QueryWrapper<>();
				TicketInfo ticketInfo = ticketInfoService
						.getOne(queryWrapper.lambda().eq(TicketInfo::getTicketid, ticketDto.getTicketid()));
				if (ObjectUtil.isNull(ticketInfo)) {
					// 新增工单
					ticketInfoSave.setCreate_name(ticketInfoSave.getUpdate_name());
					ticketInfoSave.setCreate_time(ticketInfoSave.getUpdate_time());
					boolean save = ticketInfoService.save(ticketInfoSave);
					ApiAssert.isFalse("工单信息落库失败", save);
					syncOfficeTask("1", ticketInfoSave);
				} else {
					// 更新工单
					ticketInfoSave.setId(ticketInfo.getId());
					boolean update = ticketInfoService.updateById(ticketInfoSave);
					ApiAssert.isFalse("工单信息更新库失败", update);
					syncOfficeTask("2", ticketInfoSave);
				}
				if (StrUtil.isNotBlank(ticketDto.getReply_content())) {
					// 回复工单
					QueryWrapper<TicketAgent> agentQueryWrapper = new QueryWrapper<>();
					TicketAgent ticketAgent = ticketAgentService.getOne(
							agentQueryWrapper.lambda().eq(TicketAgent::getAgent_name, ticketDto.getUpdate_name()));
					TicketReply build = TicketReply.builder().ticketid(ticketDto.getTicketid())
							.reply_content(ticketDto.getReply_content()).reply_time(ticketDto.getUpdate_time())
							.reply_type(ticketDto.getReply_type()).deal_user_name(ticketDto.getUpdate_name())
							.deal_user_id(ObjectUtil.isNotNull(ticketAgent) ? ticketAgent.getAgentid() : "").build();
					boolean save = ticketReplyService.save(build);
					ApiAssert.isFalse("回复信息落库失败", save);
					OfficeTaskReplyRequest taskReplyRequest = OfficeTaskReplyRequest.builder()
							.reply_name(ticketDto.getUpdate_name())
							.reply_time(DateUtil.formatDateTime(ticketDto.getUpdate_time()))
							.reply_content(ticketDto.getReply_content()
									+ String.format(DEAL_AGENT_NAME, ticketDto.getUpdate_name()) + TICKET_TAG)
							.ticket_code(ticketDto.getTicket_code()).build();
					syncOfficeReply(taskReplyRequest);
				}
			}
		});
	}

	@Override
	public Boolean syncTicket(ProjectTaskParamDto taskParamDto) throws ServiceException {
		log.info("【泛微】回调请求参数：{}", JSONUtil.toJsonStr(taskParamDto));
		// 通过任务id查询任务信息,判断任务是否是工单任务
		OfficeResultBody officeResultBody = syncQueryTicketTask(taskParamDto.getTask_id());
		ProjectTaskDetailDto convert = Convert.convert(new TypeReference<ProjectTaskDetailDto>() {
		}, officeResultBody.getData());
		//如果为空，不属于工单任务
		if(ObjectUtil.isNull(convert)||StrUtil.isNotBlank(convert.getOrder_number())){
			return false;
		}
		// 通过工单编码查询工单信息,判断工单信息是否存在及获取工单id
		QueryWrapper<TicketInfo> queryWrapper = new QueryWrapper<>();
		TicketInfo ticketInfo = ticketInfoService
				.getOne(queryWrapper.lambda().eq(TicketInfo::getTicket_code, convert.getOrder_number()));
		if(ObjectUtil.isNull(ticketInfo)){
			return false;
		}
		// 判断任务变更人是否存在于智齿系统
		QueryWrapper<TicketAgent> agentQueryWrapper = new QueryWrapper<>();
		TicketAgent ticketAgent = ticketAgentService
				.getOne(agentQueryWrapper.lambda().eq(TicketAgent::getAgent_name, taskParamDto.getUser_name()));
		TicketReplyRequest replyRequest = new TicketReplyRequest();
		replyRequest
				.setReply_agentid(ObjectUtil.isNull(ticketAgent) ? TICKET_SYS_ACCOUNT_ID : ticketAgent.getAgentid());
		replyRequest.setReply_agent_name(
				ObjectUtil.isNull(ticketAgent) ? TICKET_SYS_ACCOUNT_NAME : ticketAgent.getAgent_name());
		replyRequest.setGet_ticket_datetime(DateUtil.formatDateTime(new Date()));
		replyRequest.setReply_type("1");
		replyRequest.setReply_content("<p>【处理人】：" + taskParamDto.getUser_name() + "</p>" + OFFICE_TAG);
		String ticketStatus="";
		switch (convert.getWork_status()) {
			case 1:
			case 2:
				ticketStatus = "1";
				break;
			case 4:
				ticketStatus = "3";
				break;
			case 3:
				ticketStatus = "99";
				break;
			default:
				break;
		}
		replyRequest.setTicket_status(ticketStatus);
		replyRequest.setTicket_level(String.valueOf(convert.getEmergency_degree()));
		replyRequest.setTicket_title(convert.getTask_name());
		replyRequest.setTicket_content(convert.getProblem_describe());
		replyRequest.setTicketid(ticketInfo.getTicketid());
		// 调用智齿 回复工单接口
		HttpHeaders headers = new HttpHeaders();
		headers.set("token", tokenService.getToken());
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		HttpEntity<String> httpEntity = new HttpEntity<>(JSONUtil.toJsonStr(replyRequest), headers);
		ResponseEntity<TicketBaseResponse> responseEntity = restTemplate.exchange(TICKET_REPLY_URL, HttpMethod.POST,
				httpEntity, TicketBaseResponse.class);
		log.info("【智齿】工单主体返回：{}", JSONUtil.toJsonStr(responseEntity));
		if (responseEntity.getStatusCode().equals(HttpStatus.OK)
				&& "000000".equals(responseEntity.getBody().getRet_code())) {
			return true;
		}
		return false;
	}

	public void syncOfficeTask(String tag, TicketInfo ticketInfo) {
		QueryWrapper<TicketAgent> agentQueryWrapper = new QueryWrapper<>();
		TicketAgent ticketAgent = ticketAgentService
				.getOne(agentQueryWrapper.lambda().eq(TicketAgent::getAgent_name, ticketInfo.getUpdate_name()));
		if (ObjectUtil.isNull(ticketAgent)) {
			ticketAgent = ticketAgentService
					.getOne(agentQueryWrapper.lambda().eq(TicketAgent::getAgent_name, TICKET_SYS_ACCOUNT_NAME));
		}
		Integer emergencyDegree = 0;
		switch (ticketInfo.getTicket_level()) {
		case 0:
			emergencyDegree = 1;
			break;
		default:
			emergencyDegree = ticketInfo.getTicket_level();
		}
		Integer workStatus = 0;
		switch (ticketInfo.getTicket_status()) {
		case 0:
		case 1:
		case 2:
			workStatus = 2;
			break;
		case 3:
			workStatus = 4;
			break;
		case 99:
		case 98:
			workStatus = 3;
			break;
		default:
			break;
		}
		OfficeTicketTaskRquest build = OfficeTicketTaskRquest.builder().project_name(ticketInfo.getTicket_project())
				.ticker_principal(ticketInfo.getTicker_principal()).task_name(ticketInfo.getTicket_title())
				.problem_describe(ticketInfo.getTicket_content()).process_dept(ticketInfo.getDeal_group_name())
				.process_leader(ticketInfo.getDeal_agent_name()).order_primary_class(ticketInfo.getTicket_type_name())
				.order_number(ticketInfo.getTicket_code()).emergency_degree(emergencyDegree).work_status(workStatus)
				.create_channel(TicketChannelEnum.getValue(ticketInfo.getTicket_from()))
				.created_at(DateUtil.formatDateTime(ticketInfo.getUpdate_time()))
				.updated_at(DateUtil.formatDateTime(ticketInfo.getUpdate_time())).create_by(ticketAgent.getAgent_name())
				.create_phone(ticketAgent.getPhone_no()).create_email(ticketAgent.getAgent_email()).build();
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		String url = "";
		switch (tag) {
		case "1":
			url = String.format(OfficeApiConstants.OFFICE_PROJECT_TASK_ADD, surfaceUrl);
			break;
		case "2":
			url = String.format(OfficeApiConstants.OFFICE_PROJECT_TASK_MODIFY, surfaceUrl);
			break;
		default:
			break;
		}
		HttpEntity<String> httpEntity = new HttpEntity<>(JSONUtil.toJsonStr(build), headers);
		ResponseEntity<OfficeResultBody> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity,
				OfficeResultBody.class);
		log.info("【智齿】工单任务同步泛微返回：{}", JSONUtil.toJsonStr(responseEntity));
		checkResponse(responseEntity);
	}


	/**
	 * 同步工单任务查询
	 *
	 * @param taskId
	 */
	public OfficeResultBody syncQueryTicketTask(Long taskId) {
		ResponseEntity<OfficeResultBody> responseEntity = restTemplate.getForEntity(URI.create(String.format(OfficeApiConstants.OFFICE_PROJECT_TASK_QUERY, surfaceUrl) + taskId), OfficeResultBody.class);
		log.info("【智齿】回复工单返回：{}", JSONUtil.toJsonStr(responseEntity));
		return checkResponse(responseEntity);
	}


	/**
	 * 回复工单同步泛微
	 * 
	 * @param replyRequest
	 */
	public void syncOfficeReply(OfficeTaskReplyRequest replyRequest) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		HttpEntity<String> httpEntity = new HttpEntity<>(JSONUtil.toJsonStr(replyRequest), headers);
		ResponseEntity<OfficeResultBody> responseEntity = restTemplate.exchange(
				String.format(OfficeApiConstants.OFFICE_PROJECT_TASK_REPLY, surfaceUrl), HttpMethod.POST, httpEntity,
				OfficeResultBody.class);
		log.info("【智齿】回复工单返回：{}", JSONUtil.toJsonStr(responseEntity));
		checkResponse(responseEntity);
	}

	/**
	 * 校验返回体信息
	 * 
	 * @param responseEntity
	 * @return
	 */
	public static OfficeResultBody checkResponse(ResponseEntity<OfficeResultBody> responseEntity) {
		ApiAssert.isFalse("HTTP请求状态返回失败：" + responseEntity.getStatusCode(),
				responseEntity.getStatusCode().equals(HttpStatus.OK));
		OfficeResultBody officeResponse = responseEntity.getBody();
		ApiAssert.isNull("HTTP返回体为空", officeResponse);
		ApiAssert.isFalse("【泛微】请求返回状态失败：" + officeResponse.getCode(), officeResponse.getCode() == 200);
		return officeResponse;
	}

}
